﻿using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FluentValidationExample.Filters;

public sealed class ModelValidationFilter : IAsyncActionFilter, IOrderedFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (context.Controller is not ControllerBase controllerBase)
        {
            await next();

            return;
        }

        controllerBase.ProblemDetailsFactory.CreateValidationProblemDetails(context.HttpContext, context.ModelState);
        if (!context.ModelState.IsValid)
        {
            var errors = new List<ValidationFailure>();
            foreach (var item in context.ModelState)
            {
                errors.AddRange(item.Value.Errors.Select(x => new ValidationFailure()
                {
                    PropertyName = item.Key,
                    ErrorMessage = x.ErrorMessage,
                    FormattedMessagePlaceholderValues = new Dictionary<string, object>()
                    {
                        { "PropertyName", item.Key }
                    }
                }));
            }

            throw new ValidationException(errors);
        }

        await next();
    }

    public int Order => -100;
}

public sealed class ModelValidationFilter1 : IAsyncActionFilter, IOrderedFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        await next();
    }

    public int Order => 1;
}